package org.dormi.learn;

import ba.la.MyAPI;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * 解决 CustomClassLoader03的问题
 *
 * @author : dormi330
 * @since : 22/04/21
 */
public class CustomClassLoader04 {
    public static void main(String[] args) throws Exception {
        File file1 = new File("E:\\workspace\\java_basic\\class_loader\\02_res\\target\\abc.jar");
        File file2 = new File("E:\\workspace\\java_basic\\class_loader\\doc\\jackson-core-2.11.0.jar");
        URL[] urls = new URL[]{file1.toURI().toURL(), file2.toURI().toURL()};
        ClassLoader appClassLoader = CustomClassLoader04.class.getClassLoader();
        URLClassLoader loader1 = new MyClassLoader(urls, appClassLoader);


        Class<?> clazz = loader1.loadClass("foo.bar.Demo01");
        boolean ok = MyAPI.class.isAssignableFrom(clazz);
        System.out.println("MyAPI.class.isAssignableFrom(clazz)=" + ok);
        System.out.println("ba.la.MyAPI.class.getClassLoader()=" + MyAPI.class.getClassLoader());
        Class<?>[] interfaces = clazz.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface.getName() + ".class.getClassLoader()=" + anInterface.getClassLoader());
        }
        /*
        MyAPI.class.isAssignableFrom(clazz)=true
        ba.la.MyAPI.class.getClassLoader()=sun.misc.Launcher$AppClassLoader@18b4aac2
        ba.la.MyAPI.class.getClassLoader()=sun.misc.Launcher$AppClassLoader@18b4aac2
        */
    }

    /**
     * 打破双亲委派, 先自身加载, 不成功再找 parent
     * 这个类加载器 只应对加载必须加载的类
     */
    static class MyClassLoader extends URLClassLoader {
        private URL[] urls;

        public MyClassLoader(URL[] urls, ClassLoader parent) {
            super(urls, parent);
            this.urls = urls;
        }

        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            if (urls != null && urls.length > 0) {
                Class<?> c = null;
                try {
                    // 加锁, 防重复加载 TODO
                    c = findClass(name);
                } catch (ClassNotFoundException e) {
                    c = this.getParent().loadClass(name);
                }
                return c;
            }
            return super.loadClass(name);
        }
    }
}
/*
clazz.isAssignableFrom(MyAPI.class)=false
ba.la.MyAPI.class.getClassLoader()=sun.misc.Launcher$AppClassLoader@18b4aac2
ba.la.MyAPI.class.getClassLoader()=java.net.URLClassLoader@2503dbd3

原因分析:
loader1.parent=extClassLoader, 不能加载 MyAPI.class
所以 loader1 在加载 Demo01时, 一起加载了 MyAPI.class

CustomClassLoader03 也 import ba.la.MyAPI;
CustomClassLoader03 被 AppClassLoader 加载
因此 AppClassLoader 也加载了 ba.la.MyAPI

这里看出来原因了 ba.la.MyAPI 被不同的2个类加载器都加载了

*/
